Skip to content

Conversation

@JimBobSquarePants
Copy link
Member

@JimBobSquarePants JimBobSquarePants commented Nov 13, 2025

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

A proper fix for #2753 and #3000

See #3000 (comment) for the explanation of the theory.

This pull request refactors several transformation and primitive classes to improve consistency, performance, and accuracy in image processing operations. The main changes include making value type members and methods readonly for better immutability and optimization, removing unnecessary parameters related to transform space, and updating transformation logic to ensure correct coordinate space handling and more accurate results.

Transformation Logic and API Simplification

  • Removed the TransformSpace parameter and related properties from AffineTransformBuilder and transformation utility methods, simplifying the API and ensuring all transformations are consistently defined in pixel space. (src/ImageSharp/Processing/AffineTransformBuilder.cs [1] [2] [3] [4] [5] [6] [7]
  • Updated transformation processors (RotateProcessor, SkewProcessor, AffineTransformProcessor, ProjectiveTransformProcessor) to use new utility methods for canvas size calculation and matrix normalization, ensuring correct sampling and output dimensions. (src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs [1] src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs [2] [3] src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs [4] src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs [5]
  • Changed extension methods to use the new canvas size calculation for transformed images, improving output accuracy. (src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs [1] [2]

Value Type Improvements

  • Made properties and methods in Point, PointF, and SizeF structs readonly, which improves performance and thread safety by preventing modification of struct instances. (src/ImageSharp/Primitives/Point.cs [1] [2] [3] src/ImageSharp/Primitives/PointF.cs [4] [5] [6] src/ImageSharp/Primitives/SizeF.cs [7] [8]

Rectangle and Area Transformation Accuracy

  • Improved subject area transformation in ExifProfile.SyncSubject by switching from integer to floating-point rectangles for more accurate bounds calculation, and using MathF.Floor/MathF.Ceiling for coordinate rounding. (src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.csL343-R354)

Documentation and Naming Consistency

Internal Utility Refactoring

@JimBobSquarePants JimBobSquarePants added bug area:transforms breaking Signifies a binary breaking change. labels Nov 13, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request fixes off-by-one errors in image transformation operations by refactoring the coordinate space handling system. The changes remove the TransformSpace enum and consolidate all transformations to work in a consistent pixel space with proper normalization, improving accuracy in operations like rotation, skew, and projective transforms.

Key Changes

  • Removed TransformSpace parameter from transformation APIs, simplifying the interface and ensuring consistent pixel-space operations
  • Introduced matrix normalization methods (NormalizeToPixel) to correctly align transforms with pixel centers
  • Updated size calculation methods to use floating-point arithmetic for more accurate bounds computation
  • Made struct methods readonly in Point, PointF, and SizeF for better performance and immutability

Reviewed Changes

Copilot reviewed 110 out of 110 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/ImageSharp/Processing/TransformSpace.cs Removed entire enum as coordinate space handling is now unified
src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs Major refactoring of transformation utilities with new normalization and size calculation methods
src/ImageSharp/Processing/AffineTransformBuilder.cs Removed TransformSpace parameter and related properties
src/ImageSharp/Processing/ProjectiveTransformBuilder.cs Removed TransformSpace parameter and related properties
src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs Updated to use new canvas size calculation without transform space
src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs Updated to use new canvas size calculation without transform space
src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs Added matrix normalization before inversion
src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs Added matrix normalization before inversion
src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs Updated to use new canvas size calculation methods
src/ImageSharp/Primitives/Point.cs Added readonly modifier to methods for performance
src/ImageSharp/Primitives/PointF.cs Added readonly modifier to methods for performance
src/ImageSharp/Primitives/SizeF.cs Added readonly modifier to methods for performance
src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs Updated subject area transformation to use floating-point rectangles
tests/ImageSharp.Tests/TestImages.cs Added test image reference for Issue #3000
tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs Updated tests to remove TransformSpace parameter
tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs Updated test assertions to reflect corrected transformation coordinates
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs Updated test assertions for subject area
tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs Updated test assertions to reflect corrected transformation coordinates
tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs Added new test for Issue #3000 and updated existing tests
Multiple reference output images Updated test reference images to reflect corrected transformation results

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JimBobSquarePants JimBobSquarePants merged commit 24576ef into main Nov 17, 2025
9 checks passed
@JimBobSquarePants JimBobSquarePants deleted the js/fix-3000 branch November 17, 2025 01:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:transforms breaking Signifies a binary breaking change. bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rotation of AffineTransform with TransformSpace.Coordinate is off by 1 pixel

2 participants